package com.ruoyi.asset.extermination.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.asset.common.scopecode.constant.ServiceCode;
import com.ruoyi.asset.common.scopecode.service.IScopeCodeService;
import com.ruoyi.asset.extermination.constant.DisinfectionDirtConstant;
import com.ruoyi.asset.extermination.domain.Disinfection;
import com.ruoyi.asset.extermination.domain.bo.DisinfectionBo;
import com.ruoyi.asset.extermination.domain.bo.DisinfectionCommunityBo;
import com.ruoyi.asset.extermination.domain.bo.DisinfectionLocationTypeBo;
import com.ruoyi.asset.extermination.domain.bo.DisinfectionStatisticsBo;
import com.ruoyi.asset.extermination.domain.vo.DisinfectionVo;
import com.ruoyi.asset.extermination.domain.vo.ExterminationCommunityCountVo;
import com.ruoyi.asset.extermination.domain.vo.ExterminationWorkStatisticsVo;
import com.ruoyi.asset.extermination.mapper.DisinfectionMapper;
import com.ruoyi.asset.extermination.service.IDisinfectionService;
import com.ruoyi.asset.homepage.constant.CommunityConstant;
import com.ruoyi.asset.homepage.constant.ServiceTypeConstant;
import com.ruoyi.asset.tool.domain.bo.ToolStatisticsBo;
import com.ruoyi.asset.tool.service.IToolService;
import com.ruoyi.asset.workman.service.IWorkmanService;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.tools.excel.MyExcelUtil;
import com.ruoyi.common.tools.excel.base.MyExcelResult;
import com.ruoyi.common.tools.excel.listener.asset.ExterminationExcelListener;
import com.ruoyi.common.tools.utils.SerialGenerator;
import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.erecord.region.service.IRegionService;
import com.ruoyi.standingbook.extermination.service.IExterminationService;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 12276
 */
@RequiredArgsConstructor
@Service
public class DisinfectionServiceImpl implements IDisinfectionService {

    private final DisinfectionMapper disinfectionMapper;
    private final IExterminationService exterminationService;
    private IToolService toolService = SpringUtils.getBean(IToolService.class);
    private IRegionService regionService = SpringUtils.getBean(IRegionService.class);
    private IWorkmanService workmanService = SpringUtils.getBean(IWorkmanService.class);
    private ISysDictDataService sysDictDataService = SpringUtils.getBean(ISysDictDataService.class);

    private final IScopeCodeService scopeCodeService;

    private Boolean batchInsertOrUpdate(List<Disinfection> voList) {
        return this.disinfectionMapper.insertOrUpdateBatch(voList);
    }

    @Override
    public List<String> importExcel(String excelUrl) {
        List<String> errorMsgList = new ArrayList<>();

        // 生成批次号
        final String batchNo = SerialGenerator.generator.nextId();

        // excel 处理
        MyExcelResult<DisinfectionVo> excelResult = MyExcelUtil.getImportExcelData(batchNo, excelUrl,
            new ExterminationExcelListener(batchNo), DisinfectionVo.class, true);

        if (null == excelResult) {
            errorMsgList.add("未获取到要处理的数据");

            return null;
        }

        if (!excelResult.getList().isEmpty()) {
            List<Disinfection> list = new ArrayList<>();
            AtomicInteger row = new AtomicInteger(0);
            excelResult.getList().forEach(e -> {
                int currentRow = row.incrementAndGet();
                if (e.getDataCheckResult().isSucess()) {
                    Disinfection toilet = new Disinfection();

                    BeanCopyUtils.copy(e, toilet);

                    Disinfection oldLampMaintenance = getVoByCondition(toilet.getLocationName(),
                        toilet.getLocationType());

                    if (oldLampMaintenance != null) {
                        toilet.setId(oldLampMaintenance.getId());
                    } else {
                        String scopeCode = null;

                        try {
                            scopeCode = scopeCodeService.getNextScopeCode(ServiceCode.EXTERMINATION,
                                toilet.getLocationType(), "");
                        } catch (Exception ex) {
                            errorMsgList.add("获取管理范围编码失败，失败原因：" + ex.getMessage());
                        }

                        toilet.setLocationCode(scopeCode);
                    }

                    /**
                     *  如果各行数据校验通过，再遍历检查是否数据重复
                     */
                    if(excelResult.getValidateList().isEmpty()) {
                        AtomicInteger count = new AtomicInteger(0);
                        list.stream().anyMatch(f->{
                            int currentCount = count.incrementAndGet();
                            if (f.getLocationName().equals(toilet.getLocationName()) && f.getLocationType().equals(toilet.getLocationType())) {
                                errorMsgList.add(String.format("第%d行数据检查失败，失败原因：与第%s行数据重复", currentRow, currentCount));
                                return true;
                            }
                           return false;
                        });
                    }

                    list.add(toilet);
                } else {
                    errorMsgList.add(String.format("第 %d 行数据检查失败，失败原因：%s", currentRow, e.getDataCheckResult().getMsg()));
                }
            });

            if (errorMsgList.isEmpty()) {
                batchInsertOrUpdate(list);
            }
        }

        return errorMsgList;
    }

    private Disinfection getVoByCondition(String locationName, String locationType) {
        LambdaQueryWrapper<Disinfection> lqw = Wrappers.lambdaQuery();

        lqw.eq(Disinfection::getLocationName, locationName);
        lqw.eq(Disinfection::getLocationType, locationType);
        lqw.eq(Disinfection::getDelFlag,0);
        List<Disinfection> list = disinfectionMapper.selectList(lqw);

        return list.isEmpty() ? null : list.get(0);
    }

    @Override
    public int deleteExtermination(Set<Long> idsSet) {
        if (CollectionUtils.isEmpty(idsSet)) {
            return -1;
        }
        return disinfectionMapper.logicDeleteExtermination(idsSet);
    }

    @Override
    public TableDataInfo<DisinfectionVo> queryExtermination(DisinfectionBo searchBo, PageQuery pageQuery) {
        Page<DisinfectionVo> result = disinfectionMapper.selectExtermination(pageQuery.build(), searchBo);
        ArrayList<DisinfectionVo> list = new ArrayList<>();
        result.getRecords().forEach(e -> {
            DisinfectionVo disinfectionVo = new DisinfectionVo();
            BeanCopyUtils.copy(e, disinfectionVo);
            String exterminationType = sysDictDataService.selectDictLabel(DisinfectionDirtConstant.EXTERMINATION_TYPE, disinfectionVo.getLocationType());
            if (StringUtils.isNotBlank(exterminationType)){
                disinfectionVo.setLocationType(exterminationType);
            }
            list.add(disinfectionVo);

        });
        result.setRecords(list);
        return TableDataInfo.build(result);
    }

    @Override
    public List<DisinfectionVo> exportExtermination(DisinfectionBo searchBo) {
        ArrayList<DisinfectionVo> list = new ArrayList<>();
        disinfectionMapper.exportExtermination(searchBo).forEach(e -> {
            DisinfectionVo disinfectionVo = new DisinfectionVo();
            BeanCopyUtils.copy(e, disinfectionVo);
            String exterminationType = sysDictDataService.selectDictLabel(DisinfectionDirtConstant.EXTERMINATION_TYPE, disinfectionVo.getLocationType());
            if (StringUtils.isNotBlank(exterminationType)){
                disinfectionVo.setLocationType(exterminationType);
            }
            list.add(disinfectionVo);

        });
        return list;
    }

    @Override
    public DisinfectionStatisticsBo getDisinfectionCount() {
        DisinfectionStatisticsBo statisticsBo = new DisinfectionStatisticsBo();
        Integer locationCount = disinfectionMapper.selectCount();
        statisticsBo.setLocationCount(locationCount);
        int workCount = workmanService.getByServiceType(ServiceTypeConstant.EXTERMINATION);
        statisticsBo.setWorkerCount(workCount);
        ToolStatisticsBo toolStatisticsBo = toolService.getCountByServiceType(ServiceTypeConstant.EXTERMINATION);
        if (null != toolStatisticsBo) {
            statisticsBo.setEquipmentCount(toolStatisticsBo.getToolCount());
            statisticsBo.setVehicleCount(toolStatisticsBo.getVehicleCount());
        } else {
            statisticsBo.setEquipmentCount(0);
            statisticsBo.setVehicleCount(0);
        }
        return statisticsBo;
    }

    @Override
    public Map getDisinfectionCommunityCount() {
        HashMap<String, DisinfectionCommunityBo> map = new HashMap<>();
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(CommunityConstant.COMMUNITY_TYPE);
        List<SysDictData> data = sysDictDataService.selectDictDataList(sysDictData);
        for (SysDictData community : data) {
            String communityNo = regionService.getRegionIdByName(community.getDictLabel());
            List<DisinfectionLocationTypeBo> disinfectionLocationTypeBos = disinfectionMapper.selectCommunityCount(communityNo);
            disinfectionLocationTypeBos.forEach(e->{
                String locationName = sysDictDataService.selectDictLabel(DisinfectionDirtConstant.EXTERMINATION_TYPE, e.getLocationType());
                e.setLocationType(locationName);
            });
            DisinfectionCommunityBo disinfectionCommunityBo = new DisinfectionCommunityBo();
            disinfectionCommunityBo.setDisinfectionLocationTypeBoList(disinfectionLocationTypeBos);
            ToolStatisticsBo toolCount = toolService.getCountByServiceTypeAndCommunity(ServiceTypeConstant.EXTERMINATION, communityNo);
            disinfectionCommunityBo.setToolCount(toolCount.getToolCount());
            disinfectionCommunityBo.setVehicleCount(toolCount.getVehicleCount());
            int workmanCount = workmanService.getCommunityByServiceType(ServiceTypeConstant.EXTERMINATION, communityNo);
            disinfectionCommunityBo.setWorkmanCommunity(workmanCount);
            map.put(community.getDictLabel(), disinfectionCommunityBo);
        }
        return map;
    }

    @Override
    public List<ExterminationCommunityCountVo> getExterminationCountByCommunity(String date) {
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(CommunityConstant.COMMUNITY_TYPE);
        List<SysDictData> communities = sysDictDataService.selectDictDataList(sysDictData);
        ArrayList<ExterminationCommunityCountVo> countVos = new ArrayList<>();
        communities.forEach(e->{
            ExterminationCommunityCountVo exterminationCommunityCountVo = new ExterminationCommunityCountVo();
            exterminationCommunityCountVo.setCommunity(e.getDictLabel());
            String regionId = regionService.getRegionIdByName(e.getDictLabel());
            Integer numSum = disinfectionMapper.selectExterminationCountByCommunity(date, regionId);
            exterminationCommunityCountVo.setNumSum(numSum.toString());
            ToolStatisticsBo toolCount = toolService.getCommunityByServiceTypeAndDate(ServiceTypeConstant.EXTERMINATION, regionId,date);
            if (null != toolCount) {
                exterminationCommunityCountVo.setEquipmentCount(toolCount.getToolCount());
                exterminationCommunityCountVo.setVehicleCount(toolCount.getVehicleCount());
            } else {
                exterminationCommunityCountVo.setEquipmentCount(0);
                exterminationCommunityCountVo.setVehicleCount(0);
            }
            int workmanCount = workmanService.getCommunityByServiceTypeAndDate(ServiceTypeConstant.EXTERMINATION, regionId,date);
            exterminationCommunityCountVo.setWorkerCount(workmanCount);
            countVos.add(exterminationCommunityCountVo);
        });
        return countVos;
    }

    @Override
    public ExterminationWorkStatisticsVo getExterminationWorkByDate(String date) {
        ExterminationWorkStatisticsVo statisticsVo = new ExterminationWorkStatisticsVo();
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(CommunityConstant.COMMUNITY_TYPE);
        List<SysDictData> communities = sysDictDataService.selectDictDataList(sysDictData);
        ArrayList<Integer> numSumList = new ArrayList<>();
        communities.forEach(e->{
            String regionId = regionService.getRegionIdByName(e.getDictLabel());
            Integer numSum = disinfectionMapper.selectExterminationCountByCommunity(date, regionId);
            numSumList.add(numSum);
        });
        Integer totalNum = numSumList.stream().reduce(Integer::sum).orElse(0);
        statisticsVo.setTotalNum(totalNum);
        int sumByDate = exterminationService.getSumByDate(date);
        statisticsVo.setFinishedNumSum(sumByDate);
        int total = statisticsVo.getTotalNum();
        int finishedSum = statisticsVo.getFinishedNumSum();
        if (total == 0 || finishedSum == 0){
            statisticsVo.setPercent(BigDecimal.ZERO);
        } else {
            BigDecimal pec = BigDecimal.valueOf(finishedSum).divide(BigDecimal.valueOf(total),2, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100));
            pec = pec.compareTo(BigDecimal.valueOf(100)) > 0 ? BigDecimal.valueOf(100) : pec;
            statisticsVo.setPercent(pec);
        }
        return statisticsVo;
    }

    @Override
    public Integer getExterminationByDateAndCommunity(String date, String community) {
        Integer exterminationCount;
        if (StringUtils.isNotEmpty(community)) {
            String regionId = regionService.getRegionIdByName(community);
            exterminationCount = disinfectionMapper.selectExterminationCountByCommunity(date, regionId);
        } else {
            exterminationCount = disinfectionMapper.selectExterminationCountByCommunity(date, null);
        }
        if (null == exterminationCount) exterminationCount = 0;
        return exterminationCount;
    }

}
